﻿<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML dir=ltr XMLNS:MSHelp = "http://msdn.microsoft.com/mshelp" xmlns:ddue = 
"http://ddue.schemas.microsoft.com/authoring/2003/5" xmlns:xlink = 
"http://www.w3.org/1999/xlink" xmlns:tool = "http://www.microsoft.com/tooltip"
XMLNS:[default] http://ddue.schemas.microsoft.com/authoring/2003/5 =
"http://ddue.schemas.microsoft.com/authoring/2003/5"><HEAD>
  <TITLE>Request Response Sample</TITLE>
  <META content="text/html; CHARSET=utf-8" http-equiv=Content-Type></META>
  <META name=save content=history></META>
  <LINK rel=stylesheet type=text/css
  href="../../../CommonFiles/Classic.css"></LINK>

  <META name=GENERATOR content="MSHTML 8.00.6001.18783">
    <style type="text/css">
      .style1 {
      font-family: monospace;
      font-size: 100%;
      color: #000000;
      }
      .style2 {
      font-family: monospace;
      font-size: small;
      color: #000000;
      }
      </style>
  </HEAD>
<BODY>
  <DIV id=header>
    <TABLE id=topTable width="100%">
      <TBODY>
        <TR id=headerTableRow1>
          <TD align=left>
            <SPAN id=runningHeaderText></SPAN>
          </TD>
        </TR>
        <TR id=headerTableRow2>
          <TD align=left>
              <SPAN id=nsrTitle>Request/Response Sample</SPAN>
          </TD>
        </TR>
        <TR id=headerTableRow3>
          <TD></TD>
        </TR>
      </TBODY>
    </TABLE>
  </DIV>
  <DIV id=mainSection>
    <DIV id=mainBody>
      <P>
          This sample demonstrates how to implement the request/response pattern using
          Windows Azure Service Bus Topics and Subscriptions.
      </P>
      <P>
          The sample shows simple clients and servers communicating via a Service Bus 
          Topic. The SampleManager first prompts for service namespace credentials. These 
          are used to authenticate with the Access Control service, and acquire an access 
          token that proves to the Service Bus infrastructure that the client is 
          authorized to access the queue. The SampleManager creates a Topic and two
          Subscriptions one for requests and one for responses. It then creates one or more clients and servers.
          Each client sends request messages to the topic and asynchronously receives a
          message on the response subscription. The servers receives a message from the request subscription
          and sends a response message to the topic.</P>
      <P>
          Many application scenarios involve two-way communications in which a sender
          would like to receive and correlate responses for the messages that it sends.
          This is supported in Service Bus through the use of the properties SessionId and
          ReplyToSessionId on a message. Consider a pattern involving several clients that
          are sending messages and expect responses for these messages to be directed back
          to them. To enable this pattern, a given client, say client “ABC”, would set
          ReplyToSessionId=”ABC” on any messages it sends and also use MessageSession on
          a reply Topic/Subscription or Queue to listen for messages where SessionId=ABC.
          To complete the pattern, any processor of the message would set
          SessionId=ReplyToSessionId once a message has been processed.
      </P>
      <H2 class=heading>Prerequisites</H2>
      <DIV id=sectionSection0 class=section>
        <content xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
          <P xmlns="">
            If you haven't already done so, please read the release notes
            document that explains how to sign up for a Windows Azure
            account and how to configure your environment.
          </P>
        </content>
      </DIV>
      <H2 class=heading>SampleManager</H2>
      <DIV id=sectionSection1 class="section">
        <content xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
          <P xmlns="">
              The SampleManager gets user credentials and creates a NamespaceManager 
              (namespaceManager). This entity holds the credentials and is used for all 
              messaging management operations. The namespaceClient is used to create queues 
              for communication between the client(s) and server(s). The SampleManager then 
              creates client(s) and server(s), passing the user credentials to each.</P>
          <p xmlns="">
            The following code prompts for the issuer credentials and then constructs the
            listening URI using that information. The static <code>
              ServiceBusEnvironment.CreateServiceUri
            </code> function is provided to help
            construct the URI with the correct format and domain name. It is strongly
            recommended that you use this function instead of building the URI from scratch
            because the URI construction logic and format might change in future releases.            
            </code>
          </p>
          <DIV class=code xmlns="">
            <SPAN codeLanguage="CSharp">
              <TABLE cellSpacing=0 cellPadding=0 width="100%">
                <TBODY>
                  <TR>
                    <TH>C#&nbsp;</TH>
                  </TR>
                  <TR>
                    <TD colSpan=2>
                      <PRE>
                        static void Main(string[] args)
                        {
                            // Setup:
                            ParseArgs(args);
                            GetUserCredentials();
                            CreateNamespaceClient();

                            // Create topic
                            Console.WriteLine("\nCreating Topic...");
                            TopicDescription description = CreateTopic(topicPath);
                            Console.WriteLine(
                                "Created {0}", description.Path);

                            // Create request subscription
                            Console.WriteLine("\nCreating Subscriptions...");
                            SubscriptionDescription requestSub = CreateSubscription(description.Path, requestSubName, false);
                            Console.WriteLine(
                                "Created {0}/{1}, RequiresSession = {2}",
                                requestSub.TopicPath,
                                requestSub.Name,
                                requestSub.RequiresSession);
                            SubscriptionDescription responseSub = CreateSubscription(description.Path, responseSubName, true);
                            Console.WriteLine(
                                "Created {0}/{1}, RequiresSession = {2}",
                                responseSub.TopicPath,
                                responseSub.Name,
                                responseSub.RequiresSession);

                            ...
                        }

                        // Create the management entities (queue)
                        static void CreateNamespaceClient()
                        {
                            TokenProvider tokenProvider = TokenProvider.CreateSharedSecretTokenProvider(
                                ServiceBusIssuerName, ServiceBusIssuerKey);

                            Uri uri = ServiceBusEnvironment.CreateServiceUri("sb", ServiceBusNamespace, string.Empty);
                            namespaceManager = new NamespaceManager(uri, tokenProvider);
                        }

                        static TopicDescription CreateTopic(string path)
                        {
                            TopicDescription description = new TopicDescription { Path = path };

                            // Delete the topic if it already exists
                            if (namespaceManager.TopicExists(path))
                            {
                                namespaceManager.DeleteTopic(path);
                            }

                            return namespaceManager.CreateTopic(description);
                        }

                        static SubscriptionDescription CreateSubscription(string path, string name, bool sessions)
                        {
                            SubscriptionDescription description = new SubscriptionDescription
                                { TopicPath = path, Name = name, RequiresSession = sessions };

                            // Delete the subscription if it already exists
                            if (namespaceManager.SubscriptionExists(description.TopicPath, description.Name))
                            {
                                namespaceManager.DeleteSubscription(description.TopicPath, description.Name);
                            }

                            return namespaceManager.CreateSubscription(description, new CorrelationFilterExpression(name));
                        }
                      </PRE>
                    </TD>
                  </TR>
                </TBODY>
              </TABLE>
            </SPAN>
          </DIV>
          <DIV class=code xmlns="">
          </DIV>
          <p xmlns="">
              &nbsp;The SampleManager then creates client and server processes and starts them.<BR>
              <BR>
          </p>
          <DIV class=code xmlns="">
            <SPAN codeLanguage="CSharp">
              <TABLE cellSpacing="0" cellPadding="0" width="100%">
                <TBODY>
                  <TR>
                    <TH>C#&nbsp;</TH>
                  </TR>
                  <TR>
                    <TD colSpan=2>
                      <PRE class="style1">
                        static void Main(string[] args)
                        {
                            ...

                            // Start clients and servers:
                            Console.WriteLine("\nLaunching clients and servers...");
                            StartClients();
                            StartServers();

                            Console.WriteLine("\nPress [Enter] to exit.");
                            Console.ReadLine();

                            ...
                        }

                        static void StartClients()
                        {
                            ProcessStartInfo startInfo = new ProcessStartInfo();
                            startInfo.FileName = "RequestResponseSampleClient.exe";
                            for (int i = 0; i < numClients; ++i)
                            {
                                startInfo.Arguments = CreateArgs(i.ToString());
                                Process process = Process.Start(startInfo);
                                clientProcs.Add(process);
                            }
                            Thread.Sleep(500);
                            ArrangeWindows();
                        }

                        static void StartServers()
                        {
                            ProcessStartInfo startInfo = new ProcessStartInfo();
                            startInfo.FileName = "RequestResponseSampleServer.exe";
                            startInfo.Arguments = CreateArgs();
                            for (int i = 0; i < numServers; ++i)
                            {
                                Process process = Process.Start(startInfo);
                                serverProcs.Add(process);
                            }
                            Thread.Sleep(500);
                            ArrangeWindows();
                        }
                      </PRE>
                    </TD>
                  </TR>
                </TBODY>
              </TABLE>
            </SPAN>
          </DIV>
          <P xmlns="">
              Finally, the SampleManager cleans up by deleting the topics and subscriptions, as well as stopping the 
              clients and servers if necessary.</P>
          <div class="code" xmlns="">
            <span codelanguage="CSharp">
              <table cellpadding="0" cellspacing="0" width="100%">
                <tr>
                  <th>
                    C#&nbsp;
                  </th>
                </tr>
                <tr>
                  <td colspan="2">
                    <pre class="style1">
                    static void Main(string[] args)
                    {
                        ...

                        // Cleanup:
                        namespaceManager.DeleteSubscription(requestSub.TopicPath, requestSub.Name);
                        namespaceManager.DeleteSubscription(responseSub.TopicPath, responseSub.Name);
                        namespaceManager.DeleteTopic(description.Path);
                        StopClients();
                        StopServers();
                    }

                    static void StopClients()
                    {
                        foreach (Process proc in clientProcs)
                        {
                            proc.CloseMainWindow();
                        }
                    }

                    static void StopServers()
                    {
                        foreach (Process proc in serverProcs)
                        {
                            proc.CloseMainWindow();
                        }
                    }                        
                    </pre>
                  </td>
                </tr>
              </table>
            </span>
          </div>
      <H2 class=heading>Client</H2>
      <DIV id=sectionSection3 class="section">
        <content xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
          <P xmlns="">
              The Client gets user credentials as parameters from SampleManager and creates a 
              MessagingFactory (messagingFactory). This entity holds the credentials and is 
              used for all messaging runtime operations, such as opening a TopicClient to send 
              messages to the topic. The Client then creates a SubscriptionClient to the request 
              subscription. Messages are sent to the server on the topic and
              responses are processed asynchonously by calling <code>responseClient.BeginReceive()</code>.</P>
          <DIV class=code xmlns="">
            <SPAN codeLanguage="CSharp">
              <TABLE cellSpacing=0 cellPadding=0 width="100%">
                <TBODY>
                  <TR>
                    <TH>C#&nbsp;</TH>
                  </TR>
                  <TR>
                    <TD>
                      <PRE>
                        static void Main(string[] args)
                        {
                            ParseArgs(args);
                            Console.Title = "Client";

                            // Send request messages to request queue
                            TopicClient topicClient = CreateTopicClient(SampleManager.TopicPath);
                            SubscriptionClient responseClient = CreateSubscriptionClient(
                                SampleManager.TopicPath, SampleManager.ResponseSubName);

                            Console.WriteLine("Preparing to send request messages to {0}...", topicClient.Path);
                            SendMessages(topicClient, responseClient);

                            ...
                        }

                        static void SendMessages(TopicClient topicClient, SubscriptionClient responseClient)
                        {
                            // Send request messages to queue:
                            Console.WriteLine("Sending request messages to topic {0}", topicClient.Path);
                            Console.WriteLine("Receiving response messages on subscription {0}", responseClient.Name);

                            MessageSession session = responseClient.AcceptMessageSession(ClientId);

                            for (int i = 0; i < SampleManager.NumMessages; ++i)
                            {
                                // send request message
                                BrokeredMessage message = new BrokeredMessage
                                    {
                                        ReplyToSessionId = ClientId,
                                        MessageId = i.ToString(),
                                        CorrelationId = SampleManager.RequestSubName
                                    };
                
                                topicClient.Send(message);
                                SampleManager.OutputMessageInfo("REQUEST: ", message);

                                // start asynchronous receive operation
                                session.BeginReceive(TimeSpan.FromSeconds(ResponseMessageTimeout), ProcessResponse, session);
                            }


                            Console.WriteLine();
                        }

                        public static TopicClient CreateTopicClient(string topicPath)
                        {
                            TokenProvider tokenProvider = TokenProvider.CreateSharedSecretTokenProvider(
                                ServiceBusIssuerName, ServiceBusIssuerKey);

                            Uri uri = ServiceBusEnvironment.CreateServiceUri("sb", ServiceBusNamespace, string.Empty);
                            MessagingFactory messagingFactory = MessagingFactory.Create(uri, tokenProvider);

                            return messagingFactory.CreateTopicClient(topicPath);
                        }

                        public static SubscriptionClient CreateSubscriptionClient(string topicPath, string subName)
                        {
                            TokenProvider tokenProvider = TokenProvider.CreateSharedSecretTokenProvider(
                                ServiceBusIssuerName, ServiceBusIssuerKey);

                            Uri uri = ServiceBusEnvironment.CreateServiceUri("sb", ServiceBusNamespace, string.Empty);
                            MessagingFactory messagingFactory = MessagingFactory.Create(uri, tokenProvider);

                            return messagingFactory.CreateSubscriptionClient(topicPath, subName, ReceiveMode.ReceiveAndDelete);
                        }

                        static void ProcessResponse(IAsyncResult result)
                        {
                            MessageSession session = result.AsyncState as MessageSession;
                            BrokeredMessage message = session.EndReceive(result);

                            if (message == null)
                            {
                                Console.WriteLine("ERROR: Message Receive Timeout.");
                            }
                            else
                            {
                                SampleManager.OutputMessageInfo("RESPONSE: ", message);
                            }
                        }
                      </PRE>
                    </TD>
                  </TR>
                </TBODY>
              </TABLE>
            </SPAN>
          </DIV>
        </DIV>
      <H2 class=heading>Server</H2>
      <DIV id=sectionSection2 class=section>
        <content xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
          <P xmlns="">
              The Server also gets user credentials as parameters from SampleManager and 
              creates a MessagingFactory (messagingFactory). This entity holds the credentials 
              and is used for all messaging runtime operations, such as opening a TopicClient to 
              receive messages from the topic. The Server then creates a SubscriptionClient to the request 
              subscription and starts receiving and responding to request messages:</P>
          <DIV class=code xmlns="">
            <SPAN codeLanguage="CSharp">
              <TABLE cellSpacing=0 cellPadding=0 width="100%">
                <TBODY>
                  <TR>
                    <TH>C#&nbsp;</TH>
                  </TR>
                  <TR>
                    <TD colSpan=2>
                      <PRE class="style1">
                        static void Main(string[] args)
                        {
                            ParseArgs(args);

                            // Receive request messages from request queue
                            Console.Title = "Server";
                            TopicClient topicClient = CreateTopicClient(SampleManager.TopicPath);
                            SubscriptionClient requestClient = CreateSubscriptionClient(
                                SampleManager.TopicPath, SampleManager.RequestSubName);

                            Console.WriteLine("Ready to receive messages from {0}/{1}...", requestClient.TopicPath, requestClient.Name);
                            ReceiveMessages(topicClient, requestClient);
                        
                            ...
                        }

                        static void ReceiveMessages(TopicClient topicClient, SubscriptionClient requestClient)
                        {
                            // Read all the messages from subscription:
                            BrokeredMessage request;
                            while ((request = requestClient.Receive(TimeSpan.FromSeconds(ReceiveMessageTimeout))) != null)
                            {
                                SampleManager.OutputMessageInfo("REQUEST: ", request);

                                BrokeredMessage response = new BrokeredMessage
                                    {
                                        SessionId = request.ReplyToSessionId,
                                        MessageId = request.MessageId,
                                        CorrelationId = SampleManager.ResponseSubName
                                    };

                                topicClient.Send(response);
                                SampleManager.OutputMessageInfo("RESPONSE: ", response);
                            }
                        }

                        public static TopicClient CreateTopicClient(string topicPath)
                        {
                            TokenProvider tokenProvider = TokenProvider.CreateSharedSecretTokenProvider(
                                ServiceBusIssuerName, ServiceBusIssuerKey);

                            Uri uri = ServiceBusEnvironment.CreateServiceUri("sb", ServiceBusNamespace, string.Empty);
                            MessagingFactory messagingFactory = MessagingFactory.Create(uri, tokenProvider);

                            return messagingFactory.CreateTopicClient(topicPath);
                        }

                        public static SubscriptionClient CreateSubscriptionClient(string topicPath, string subName)
                        {
                            TokenProvider tokenProvider = TokenProvider.CreateSharedSecretTokenProvider(
                                ServiceBusIssuerName, ServiceBusIssuerKey);

                            Uri uri = ServiceBusEnvironment.CreateServiceUri("sb", ServiceBusNamespace, string.Empty);
                            MessagingFactory messagingFactory = MessagingFactory.Create(uri, tokenProvider);

                            return messagingFactory.CreateSubscriptionClient(topicPath, subName, ReceiveMode.ReceiveAndDelete);
                        }
                      </PRE>
                    </TD>
                  </TR>
                </TBODY>
              </TABLE>
            </SPAN>
          </DIV>
        </content>
      </DIV>
    </DIV>
    <H2 class=heading>Running the Sample</H2>
    <DIV id=DIV1 class=section>
      <content
xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
        <P xmlns="">
            To run the sample, build the solution in Visual Studio or from the command line, 
            then run the resulting SampleManager.exe executable file. The program will 
            prompt for your service namespace and the issuer credentials. For the 
            issuer secret, be sure to use the &quot;Default Issuer Key&quot; value (typically &quot;owner&quot;) 
            from the portal, rather than one of the management keys.
        </P>
        <P xmlns="">
          <B>Expected Output - SampleManager </B>
        </P>
        <DIV class=code xmlns="">
          <SPAN codeLanguage="other">
            <TABLE cellSpacing=0 cellPadding=0 width="100%">
              <TBODY>
                <TR>
                  <TD>
                    <PRE class="style2">
                         Please provide the namespace to use:
                        &lt;service namespace&gt;
                        Please provide the Issuer name to use:
                        &lt;issuer name&gt;
                        Please provide the Issuer key to use:
                        &lt;issuer key&gt;

                        Creating Topic...
                        Created RequestResponseTopic

                        Creating Subscriptions...
                        Created RequestResponseTopic/Request, RequiresSession = False
                        Created RequestResponseTopic/Response, RequiresSession = True

                        Launching clients and servers...

                        Press [Enter] to exit.
                    </PRE>
                  </TD>
                </TR>
              </TBODY>
            </TABLE>
          </SPAN>
        </DIV>
        <P xmlns="">
          <B>Expected Output - Client</B>
        </P>
        <DIV class=code xmlns="">
          <SPAN codeLanguage="other">
            <TABLE cellSpacing=0 cellPadding=0 width="100%">
              <TBODY>
                <TR>
                  <TD colSpan=2>
                    <PRE class="style2">
                        Preparing to send request messages to RequestQueue...
                        Sending request messages to queue RequestQueue
                        Receiving response messages on queue ResponseQueue
                        REQUEST: 0 - Client 0.
                        REQUEST: 1 - Client 0.
                        REQUEST: 2 - Client 0.
                        REQUEST: 3 - Client 0.
                        REQUEST: 4 - Client 0.
                        REQUEST: 5 - Client 0.
                        REQUEST: 6 - Client 0.
                        REQUEST: 7 - Client 0.
                        REQUEST: 8 - Client 0.
                        REQUEST: 9 - Client 0.


                        Client finished sending requests.
                        RESPONSE: 0 - Client 0.
                        RESPONSE: 1 - Client 0.
                        RESPONSE: 2 - Client 0.
                        RESPONSE: 3 - Client 0.
                        RESPONSE: 4 - Client 0.
                        RESPONSE: 5 - Client 0.
                        RESPONSE: 6 - Client 0.
                        RESPONSE: 7 - Client 0.
                        RESPONSE: 8 - Client 0.
                        RESPONSE: 9 - Client 0.
                    </PRE>
                  </TD>
                </TR>
              </TBODY>
            </TABLE>
          </SPAN>
        </DIV>
        <P xmlns="">
          <B>Expected Output - Server</B>
        </P>
        <DIV class=code xmlns="">
          <SPAN codeLanguage="other">
            <TABLE cellSpacing=0 cellPadding=0 width="100%">
              <TBODY>
                <TR>
                  <TD colSpan=2>
                    <PRE>
                        Ready to receive messages from RequestQueue...
                        Reading messages from queue RequestQueue
                        REQUEST: 0 - Client 2.
                        RESPONSE: 0 - Client 2.
                        REQUEST: 0 - Client 0.
                        RESPONSE: 0 - Client 0.
                        REQUEST: 0 - Client 1.
                        RESPONSE: 0 - Client 1.
                        REQUEST: 0 - Client 3.
                        RESPONSE: 0 - Client 3.
                        REQUEST: 1 - Client 2.
                        RESPONSE: 1 - Client 2.
                        REQUEST: 1 - Client 0.
                        RESPONSE: 1 - Client 0.
                        REQUEST: 1 - Client 1.
                        RESPONSE: 1 - Client 1.
                        REQUEST: 1 - Client 3.
                        RESPONSE: 1 - Client 3.
                        REQUEST: 2 - Client 2.
                        RESPONSE: 2 - Client 2.
                        REQUEST: 2 - Client 3.
                        RESPONSE: 2 - Client 3.
                        REQUEST: 2 - Client 1.
                        RESPONSE: 2 - Client 1.
                        REQUEST: 2 - Client 0.
                        RESPONSE: 2 - Client 0.
                        
                        ...

                        REQUEST: 8 - Client 0.
                        RESPONSE: 8 - Client 0.
                        REQUEST: 8 - Client 1.
                        RESPONSE: 8 - Client 1.
                        REQUEST: 8 - Client 2.
                        RESPONSE: 8 - Client 2.
                        REQUEST: 8 - Client 3.
                        RESPONSE: 8 - Client 3.
                        REQUEST: 9 - Client 0.
                        RESPONSE: 9 - Client 0.
                        REQUEST: 9 - Client 1.
                        RESPONSE: 9 - Client 1.
                        REQUEST: 9 - Client 3.
                        RESPONSE: 9 - Client 3.
                        REQUEST: 9 - Client 2.
                        RESPONSE: 9 - Client 2.

                        Server complete.
                    </PRE>
                  </TD>
                </TR>
              </TBODY>
            </TABLE>
          </SPAN>
        </DIV>
      </content>
    </DIV>
    <!--[if gte IE 5]><tool:tip avoidmouse="false" element="languageFilterToolTip"></tool:tip><![endif]-->
  </DIV>
</BODY></HTML>
